package com.hm.hall.commons.util;

import com.hm.hall.commons.constans.GameConstans;
import com.hm.hall.commons.constans.RedisSecondConstants;
import com.hm.hall.commons.constans.ValueConstants;
import org.apache.commons.io.FileUtils;

import javax.imageio.ImageIO;
import javax.imageio.ImageReadParam;
import javax.imageio.ImageReader;
import javax.imageio.stream.FileImageInputStream;
import javax.imageio.stream.ImageInputStream;
import java.awt.*;
import java.awt.geom.AffineTransform;
import java.awt.geom.RoundRectangle2D;
import java.awt.image.AffineTransformOp;
import java.awt.image.BufferedImage;
import java.io.*;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

/**
 * 图片工具类
 */
public class ImageUtils {
    public static final String IMG_FILE_SUFFIX = ".jpg";
    public static final String BASE_DIR = "E:/data/wepoker/wepoker/";
    // public static final String BASE_DIR = "/data/wepoker/";

    public static final String TEMP_DIR = "E:/data/wepoker/temp-wepoker/";
    public static final String CIRCULAR_POINT = BASE_DIR + "circular_point_%s.png";
    public static final String AVATAR_PREFIX = "avatar_";

    // 第一个参数是外部字体名，第二个是字体大小
    public static Font loadFont(String fontFileName, float fontSize) {

        try {
            File file = new File(fontFileName);
            FileInputStream fontFile = new FileInputStream(file);
            Font dynamicFont = Font.createFont(Font.TRUETYPE_FONT, fontFile);
            Font dynamicFontPt = dynamicFont.deriveFont(fontSize);
            fontFile.close();
            return dynamicFontPt;
        } catch (Exception e)// 异常处理
        {
            e.printStackTrace();
            return new Font("宋体", Font.PLAIN, (int) fontSize);
        }
    }

    // 获得项目资源文件夹下的Image
    public static Image readProjectImage(String file) {
        try {
            InputStream inputStream = Thread.currentThread().getContextClassLoader().getResourceAsStream(file);
            Image image = ImageIO.read(inputStream);
            inputStream.close();
            return image;
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * @param fileUrl 文件绝对路径或相对路径
     * @return 读取到的缓存图像
     * @throws IOException 路径错误或者不存在该文件时抛出IO异常
     */
    public static BufferedImage getBufferedImage(String fileUrl) throws IOException {
        File f = new File(fileUrl);
        return ImageIO.read(f);
    }

    /**
     * 功能描述: <br>
     * 〈调整图像到固定大小〉
     * <p>
     * 源图像文件地址
     *
     * @param width     缩放后的宽度
     * @param height    缩放后的高度
     * @param isPadding 是否补白
     */
    public final static BufferedImage changeSize(BufferedImage bufferedImage, int width, int height,
                                                 boolean isPadding) {
        // 缩放比例
        double ratio = 0.0;
        Image image = bufferedImage.getScaledInstance(width, height, Image.SCALE_SMOOTH);
        // 计算缩放比例
        if (bufferedImage.getHeight() > bufferedImage.getWidth()) {
            ratio = (new Integer(height)).doubleValue() / bufferedImage.getHeight();
        } else {
            ratio = (new Integer(width)).doubleValue() / bufferedImage.getWidth();
        }
        AffineTransformOp op = new AffineTransformOp(AffineTransform.getScaleInstance(ratio, ratio), null);
        image = op.filter(bufferedImage, null);

        // 是否需要补白
        if (isPadding) {
            BufferedImage tempBufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
            Graphics2D graphics2d = tempBufferedImage.createGraphics();
            graphics2d.setColor(Color.white);
            graphics2d.fillRect(0, 0, width, height);
            if (width == image.getWidth(null)) {
                graphics2d.drawImage(image, 0, (height - image.getHeight(null)) / 2, image.getWidth(null),
                        image.getHeight(null), Color.white, null);
            } else {
                graphics2d.drawImage(image, (width - image.getWidth(null)) / 2, 0, image.getWidth(null),
                        image.getHeight(null), Color.white, null);
            }
            graphics2d.dispose();
            image = tempBufferedImage;
        }
        return (BufferedImage) image;
    }

    /**
     * 功能描述: <br>
     * 〈利用画布生成新的图片〉
     *
     * @param backImage 背景图文件
     *                  前景图文件
     * @return descImage 生成图文件
     * @throws IOException
     */
    public static BufferedImage mergeImage(List<BufferedImage> imageList, BufferedImage backImage) throws IOException {
        int offsetHeight = 0;
        // 输出图片宽度
        int width = imageList.get(0).getWidth();
        // 输出图片高度
        int height = 0;
        for (BufferedImage buffImg : imageList) {
            height += buffImg.getHeight();
        }
        BufferedImage descBufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_4BYTE_ABGR);
        Graphics2D graphics2d = (Graphics2D) descBufferedImage.getGraphics();
        for (BufferedImage buffImg : imageList) {
            graphics2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
            // 往画布上添加图片,并设置边距
            graphics2d.drawImage(buffImg, null, 0, offsetHeight);
            offsetHeight += buffImg.getHeight();
        }
        graphics2d.dispose();
        if (backImage == null)
            return addPromptImg(descBufferedImage);
        if (imageList.size() < 12)
            return addPromptImg(drawImg(backImage, descBufferedImage, 0, 0));
        // 计算超出背景高度
        int spareHight = (imageList.size() - 11) * imageList.get(1).getHeight();
        // 生成背景镜像图片
        BufferedImage invertedImage = invertedImage(backImage);
        // 截取镜像图片超出高度 生成新的背景图片
        List<BufferedImage> newImageList = new ArrayList<>();
        newImageList.add(cutImage(backImage, 0, 0, width, backImage.getHeight() - 1));
        newImageList.add(cutImage(invertedImage, 0, 1, width, spareHight));
        return addPromptImg(drawImg(mergeImage(newImageList, null), descBufferedImage, 0, 0));
    }

    public static BufferedImage addPromptImg(BufferedImage srcImage) throws IOException {
        int height = srcImage.getHeight();
        int width = srcImage.getWidth();
        Font font = new Font("微软雅黑", Font.PLAIN, 26);
        Color color = new Color(177, 170, 178);
        String promptStr1 = "仅供好友休闲 严禁任何赌博";
        int fontWidth = calculateStrWidth(font, promptStr1);
        drawString(srcImage, promptStr1, (width - fontWidth) / 2, height - 70, color, font);
        drawString(srcImage, "自觉远离赌博 共创文明娱乐", (width - fontWidth) / 2, height - 30, color, font);
        // BufferedImage erweimaImg = ImageIO.read(new
        // File("/data/pic_src/erweima.png"));
        // drawImg(srcImage, erweimaImg,width-184 , height-97);
        return srcImage;
    }


    /**
     * 获取用户头像url 到缓存文件夹
     *
     * @param avatar
     * @param userId
     * @return
     * @throws IOException
     * @throws MalformedURLException
     */
    public static BufferedImage getAvatarImg(String avatar, long userId, int size)
            throws IOException, MalformedURLException {
        String tempFileName = AVATAR_PREFIX + userId + IMG_FILE_SUFFIX;
        String avatarFileName = TEMP_DIR + tempFileName;
        File avatarFile = null;
        try {
            avatarFile = new File(avatarFileName);
            if (avatarFile.exists()) {
                Long time = avatarFile.lastModified();
                if (System.currentTimeMillis() > (time + RedisSecondConstants.DAY_SECOND)) {// 只图片缓存1天
                    FileUtils.copyURLToFile(new URL(avatar), avatarFile);
                }
            } else {
                FileUtils.copyURLToFile(new URL(avatar), avatarFile);
            }
        } catch (Exception e) {// 读取不到头像使用默认头像
            FileUtils.copyURLToFile(new URL(GameConstans.DEFAULT_AVATAR), avatarFile);
        }
        BufferedImage avatarImg = null;
        if (null != avatarFile) {
            avatarImg = ImageIO.read(avatarFile);
            // 改变图片大小
            avatarImg = changeSize(avatarImg, size, size, false);
            // 设置头像为圆形
            avatarImg = setRadius(avatarImg, size, ValueConstants.DEFAULT_ZERO);
        }
        return avatarImg;
    }

    /**
     * 功能描述: 文字超过限定宽度进行缩写
     *
     * @param font     字体
     * @param str      字符串
     * @param maxWidth 限制宽度
     * @return
     */
    @SuppressWarnings("restriction")
    public static String textMore(Font font, String str, int maxWidth) {
        FontMetrics fm = sun.font.FontDesignMetrics.getMetrics(font);
        if (fm.stringWidth(str) > maxWidth) {
            str = str.substring(0, str.length() - 1);
            str = textMore(font, str, maxWidth);
            if (!str.endsWith("..."))
                str = str + "...";
        }
        return str;
    }

    public static BufferedImage setBackdrop(int hight, int width, int fontSize, Color color, int grade) {
        BufferedImage buffImg = new BufferedImage(width, hight, BufferedImage.TYPE_INT_RGB);
        Graphics2D bg = buffImg.createGraphics();
        // 设置区域颜色
        bg.setColor(color);
        // 填充区域并确定区域大小位置
        bg.fillRect(0, 0, width, hight);
        // 设置字体颜色，先设置颜色，再填充内容
        Color strColor = Color.white;
        String strGrade = "0";
        if (grade > 0) {
            strColor = new Color(226, 34, 60);
            strGrade = "+" + grade;
        } else if (grade < 0) {
            strColor = new Color(0, 186, 79);
            strGrade = "" + grade;
        }
        bg.setColor(strColor);
        // 设置字体
        Font tipFont = new Font("微软雅黑", Font.PLAIN, fontSize);
        bg.setFont(tipFont);
        int x = 0;
        if (fontSize == 46) {
            x = xAxis(strGrade, 364, 76, fontSize);
        } else {
            x = xAxis(strGrade, 404, 76, fontSize);
        }
        bg.drawString(strGrade, x, 55);
        bg.dispose();
        return buffImg;
    }

    /**
     * 计算分数x坐标
     */
    private static int xAxis(String strGrade, int x, int width, int size) {
        int Text_width = strGrade.length() * size / 2;
        int Temp_width = (width - Text_width) / 2;
        return x + Temp_width;
    }

    /**
     * 功能描述: 计算字体所占宽度
     *
     * @param font 字体
     * @param str  字符串
     * @return
     */
    @SuppressWarnings("restriction")
    public static int calculateStrWidth(Font font, String str) {
        if (str == null || str.equals(""))
            return 0;
        FontMetrics fm = sun.font.FontDesignMetrics.getMetrics(font);
        return fm.stringWidth(str);
    }

    public static BufferedImage drawString(BufferedImage buffImg, String str, int x, int y, Color color, Font font) {
        Graphics g = buffImg.getGraphics();
        g.setFont(font);
        g.setColor(color);
        // 10,20 表示这段文字在图片上的位置(x,y) .第一个是你设置的内容。
        g.drawString(str, x, y);
        g.dispose();
        return buffImg;
    }

    public static BufferedImage drawImg(BufferedImage buffImg, BufferedImage appendImg, int x, int y) {
        Graphics g = buffImg.getGraphics();
        g.drawImage(appendImg, x, y, null);
        g.dispose();
        return buffImg;
    }

    /**
     * 图片设置圆角
     *
     * @param srcImage
     * @param radius
     * @param border
     * @return
     * @throws IOException
     */
    public static BufferedImage setRadius(BufferedImage srcImage, int radius, int border) throws IOException {
        int width = srcImage.getWidth();
        int height = srcImage.getHeight();

        BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
        Graphics2D gs = image.createGraphics();
        gs.setComposite(AlphaComposite.Src);
        gs.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        gs.setColor(new Color(206, 166, 255)); // #cea6ff
        gs.fill(new RoundRectangle2D.Float(0, 0, width, height, radius, radius));
        gs.setComposite(AlphaComposite.SrcAtop);
        gs.drawImage(setClip(srcImage, radius), 0, 0, null);
        if (border != 0) {
            gs.setColor(new Color(206, 166, 255));
            gs.setStroke(new BasicStroke(border));
            gs.drawRoundRect(0, 0, width - border / 2, height - border / 2, radius, radius);
        }
        gs.dispose();
        return image;
    }

    /**
     * 图片切圆角
     *
     * @param srcImage
     * @param radius
     * @return
     */
    public static BufferedImage setClip(BufferedImage srcImage, int radius) {
        int width = srcImage.getWidth();
        int height = srcImage.getHeight();
        BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
        Graphics2D gs = image.createGraphics();
        gs.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        gs.setClip(new RoundRectangle2D.Double(0, 0, width, height, radius, radius));
        gs.drawImage(srcImage, 0, 0, null);
        gs.dispose();
        return image;
    }

    /**
     * 图片到byte数组
     */
    public static byte[] image2byte(String path) {
        byte[] data = null;
        FileImageInputStream input = null;
        try {
            input = new FileImageInputStream(new File(path));
            ByteArrayOutputStream output = new ByteArrayOutputStream();
            byte[] buf = new byte[1024];
            int numBytesRead = 0;
            while ((numBytesRead = input.read(buf)) != -1) {
                output.write(buf, 0, numBytesRead);
            }
            data = output.toByteArray();
            output.close();
            input.close();
        } catch (FileNotFoundException ex1) {
            ex1.printStackTrace();
        } catch (IOException ex1) {
            ex1.printStackTrace();
        }
        return data;
    }

    /**
     * 图像倒转 旋转180度再水平翻转
     *
     * @param bufferedimage 目标图像
     * @return
     */
    public static BufferedImage invertedImage(final BufferedImage bufferedimage) {
        return flipImage(rotateImage(bufferedimage, 180));
    }

    /**
     * 旋转图片为指定角度
     *
     * @param bufferedimage 目标图像
     * @param degree        旋转角度
     * @return
     */
    public static BufferedImage rotateImage(final BufferedImage bufferedimage, final int degree) {
        int w = bufferedimage.getWidth();
        int h = bufferedimage.getHeight();
        int type = bufferedimage.getColorModel().getTransparency();
        BufferedImage img;
        Graphics2D graphics2d;
        (graphics2d = (img = new BufferedImage(w, h, type)).createGraphics())
                .setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
        graphics2d.rotate(Math.toRadians(degree), w / 2, h / 2);
        graphics2d.drawImage(bufferedimage, 0, 0, null);
        graphics2d.dispose();
        return img;
    }

    /**
     * 水平翻转图像
     *
     * @param bufferedimage 目标图像
     * @return
     */
    public static BufferedImage flipImage(final BufferedImage bufferedimage) {
        int w = bufferedimage.getWidth();
        int h = bufferedimage.getHeight();
        BufferedImage img;
        Graphics2D graphics2d;
        (graphics2d = (img = new BufferedImage(w, h, bufferedimage.getColorModel().getTransparency())).createGraphics())
                .drawImage(bufferedimage, 0, 0, w, h, w, 0, 0, h, null);
        graphics2d.dispose();
        return img;
    }

    /**
     * @param image  内存中的图片 BufferedImage对象
     * @param x      开始剪切的x坐标
     * @param y      开始剪切的y坐标
     * @param width  剪切的宽度
     * @param height 剪切的高度
     * @return<br>
     */
    public static BufferedImage cutImage(BufferedImage image, int x, int y, int width, int height) {
        try {
            Iterator<ImageReader> it = ImageIO.getImageReadersByFormatName("png");
            ImageReader reader = it.next();
            ImageInputStream iis = ImageIO
                    .createImageInputStream(new ByteArrayInputStream(bufferedImageToByteArray(image, "png")));
            reader.setInput(iis, true);
            ImageReadParam param = reader.getDefaultReadParam();
            Rectangle rect = new Rectangle(x, y, width, height);
            // 提供一个 BufferedImage，将其用作解码像素数据的目标。
            param.setSourceRegion(rect);
            BufferedImage bi = reader.read(0, param);
            iis.close();
            return bi;
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 转换BufferedImage 数据为byte数组
     * <p>
     * Image对象
     *
     * @param format image格式字符串.如"gif","png"
     * @return byte数组
     */
    public static byte[] bufferedImageToByteArray(BufferedImage bImage, String format) {
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        try {
            ImageIO.write(bImage, format, out);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return out.toByteArray();
    }

    /**
     * png图片转为jpg（透明度处理）
     * <p>
     * Image对象
     */
    public static BufferedImage pngImageToJpgImage(BufferedImage srcImage) {
        BufferedImage newBufferedImage = new BufferedImage(srcImage.getWidth(), srcImage.getHeight(),
                BufferedImage.TYPE_INT_RGB);
        Graphics2D g = newBufferedImage.createGraphics();
        g.drawImage(srcImage, 0, 0, Color.WHITE, null);
        g.dispose();
        return newBufferedImage;
    }
}